class Watermark {
  constructor(props) {
    const {
      content, verify, fontSize, fontFamily, fontWeight, color, alpha, width, height, rotate,
      zIndex, backgroundPosition, onWatermarkNull,
    } = props;

    if (content === undefined || content === null || content === '') {
      console.error('请输入水印文本 content');
      if (onWatermarkNull) {
        onWatermarkNull();
      } else {
        this.defaultWatermarkNull?.();
      }
    }

    this.content = content; // 水印文本【**`必填`**】
    this.fontWeight = fontWeight || 'normal'; // 字体的粗细
    this.fontSize = fontSize ? `${fontSize}px` : '14px'; // font-size px
    this.fontFamily = fontFamily || 'sans-serif'; // font-family
    this.font = `${this.fontWeight} ${this.fontSize} ${this.fontFamily}`;
    this.color = color || '#666666'; // 水印文本颜色
    this.globalAlpha = alpha || 0.15; // 水印文本透明度 0~1 0 表示完全透明，1 表示完全不透明
    this.width = width || 200; // 单个水印宽度 px
    this.height = height || 170; // 单个水印高度 px
    this.rotate = ((rotate || 330) * Math.PI) / 180; // 水印旋转角度，以左上角为原点旋转，注意旋转角度影响水印文本显示
    this.zIndex = zIndex || 2147483647; // z-index
    this.backgroundPosition = backgroundPosition || '0px 0px, 0px 0px'; // 水印背景图片位置 background-position
    this.watermark = null; // 水印 dom
    this.onWatermarkNullProp = onWatermarkNull;

    this.watermarkObserve = null; // 水印节点监听
    this.bodyObserve = null; // body监听
    this.verify = verify; // 对比文本是否一致
    this.image = this.getImage(); // 水印图片 【位置保持在最后，因为这里是函数调用】
  }

  // 处理水印消失、内容与原文本不一致或者创建失败
  onWatermarkNull = () => {
    if (this.onWatermarkNullProp) {
      this.onWatermarkNullProp?.();
    } else {
      this.defaultWatermarkNull?.();
    }
  };

  // 创建高清Canvas
  createHDCanvas = (width = 300, height = 150) => {
    const ratio = window.devicePixelRatio || 1;
    const canvas = document.createElement('canvas');
    canvas.width = width * ratio; // 实际渲染像素
    canvas.height = height * ratio; // 实际渲染像素
    canvas.style.width = `${width}px`; // 控制显示大小
    canvas.style.height = `${height}px`; // 控制显示大小
    canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
    return canvas;
  }

  // canvas画文字
  draw = () => {
    // 1.创建canvas元素
    const canvas = this.createHDCanvas(this.width, this.height);

    document.body.appendChild(canvas);

    // 2.获取上下文
    const context = canvas.getContext('2d');

    // // 3.画两条相交垂线,测试用
    // context.moveTo(0, canvas.height);
    // context.lineTo(canvas.width, canvas.height);
    // context.stroke();
    //
    // context.beginPath();
    // context.moveTo(canvas.width, 0);
    // context.lineTo(canvas.width, canvas.height);
    // context.stroke();

    // 3.配置画笔🖌

    // 字体
    context.font = this.font;

    // 对齐方式
    // context.textAlign = 'left';
    // context.textAlign = 'right';
    context.textAlign = 'center';

    // 底部对齐方式(top  bottom middle)
    // context.textBaseline = 'bottom';
    // context.textBaseline = 'top';
    context.textBaseline = 'middle';
    // 填充色
    context.fillStyle = this.color;
    // 设置全局画笔透明度
    context.globalAlpha = this.globalAlpha;

    // 平移转换,修改原点
    context.translate(this.width / 2, this.height / 2);

    // 旋转转换(弧度数)
    context.rotate(this.rotate);

    if (this.verify && this.content !== this.verify) {
      this.onWatermarkNull?.();
    }

    // 实心文字fillText(文字内容,文字左下角的X坐标,文字左下角的Y坐标);
    context.fillText(this.content, 0, 0);

    return canvas;
  };

  // canvas 转 image
  getImage = () => {
    let image;
    try {
      const canvas = this.draw();
      image = canvas.toDataURL('image/png', 1);
      canvas.remove();
    } catch {
      this.onWatermarkNull?.();
    }
    return image;
  };

  // 生成水印节点
  create = () => {
    try {
      this.watermark = document.createElement('div');

      // 占用影响水印显示的css 属性
      this.watermark.style.cssText = `
      display: block !important;
      z-index: ${this.zIndex} !important;
      height: auto !important;
      width: auto !important;
      top: auto !important;
      left: auto !important;
      right: auto !important;
      bottom: auto !important;
      background: none;
      visibility: visible !important;
      transform: none !important;
      opacity: 1 !important;
    `;

      const watermarkInner = document.createElement('div');
      watermarkInner.style.cssText = `
      display: block !important;
      z-index: ${this.zIndex} !important;
      position: fixed !important;
      pointer-events: none !important;
      height: 100% !important;
      width: 100% !important;
      top: 0px !important;
      left: 0px !important;
      background-image: url(${this.image}) !important;
      background-size: ${this.width}px ${this.height}px !important;
      background-repeat: repeat !important;
      background-position: ${this.backgroundPosition} !important;
      visibility: visible !important;
      transform: none !important;
      right: auto !important;
      bottom: auto !important;
      opacity: 1 !important;
    `;

      this.watermark.append(watermarkInner);
      document.body.appendChild(this.watermark);

      setTimeout(() => {
        this.watermarkObserve?.disconnect?.();
        this.bodyObserve?.disconnect?.();
        this.observeWatermarkInnerDom();
        this.bodyObserveWatermarkDom();
      });
    } catch {
      this.onWatermarkNull?.();
    }
  };

  // 监听水印节点dom变化，重新渲染
  observeWatermarkInnerDom = () => {
    // 选择需要观察变动的节点
    const targetNode = this.watermark;

    // 观察器的配置（需要观察什么变动）
    // subtree：是否监听子节点的变化
    const config = {
      attributes: true, childList: true, subtree: true,
    };

    // 当观察到变动时执行的回调函数
    const callback = (mutationsList) => {
      mutationsList.forEach((item) => {
        item.target?.remove();
      });
      this.watermark?.remove();
    };

    try {
      // 创建一个观察器实例并传入回调函数
      const observer = new MutationObserver(callback);

      // 以上述配置开始观察目标节点
      observer.observe(targetNode, config);

      this.watermarkObserve = observer;
    } catch {
      this.onWatermarkNull?.();
    }

    // 之后，可停止观察
    // observer.disconnect();
  };

  // 监听水印节点dom变化，重新渲染
  bodyObserveWatermarkDom = () => {
    // 选择将观察突变的节点
    const targetNode = document.querySelector('body');

    // 观察者的选项(观察哪些突变)
    // subtree：是否监听子节点的变化
    const config = {
      attributes: true, childList: true, subtree: true, characterData: true,
    };

    // 当观察到突变时执行的回调函数
    const callback = (mutationsList) => {
      mutationsList.forEach((item) => {
        if (item.target === this.watermark) {
          item?.removedNodes?.[0]?.remove();
          item?.target?.remove();
          this.watermark = null;
          this.create();
          return;
        }
        if (item.removedNodes.length && item.removedNodes[0] === this.watermark) {
          this.create();
        }
      });
      if (!this.watermark) {
        this.onWatermarkNull?.();
      }
    };

    try {
      // 创建一个观察者实例并添加回调函数
      const observer = new MutationObserver(callback);
      // 根据配置开始观察目标节点的突变
      observer.observe(targetNode, config);
      this.bodyObserve = observer;
    } catch {
      this.onWatermarkNull?.();
    }
  };

  // 水印消失或者创建失败后的默认回调
  defaultWatermarkNull = () => {
    // eslint-disable-next-line no-alert
    window.alert('水印消失了，请刷新页面以保证信息安全');
  }
}

export default Watermark;
